//
//  OAWebDriver.m
//  OARetail
//
//  Created by ChenJie on 5/15/20.
//  Copyright © 2020 Mist. All rights reserved.
//

#import "OAWebDriver.h"
#import <AFNetworking/AFNetworking.h>

NSString * const OAWebContentTypeKey = @"Content-Type";
NSString * const OAWebContentTypeApplicationJson = @"application/json";
NSString * const OAWebContentTypeFormUrlencoded = @"application/x-www-form-urlencoded";

@interface OAWebDriver ()

@property (nonatomic, strong) AFHTTPSessionManager *sessionManager;

@end

@implementation OAWebDriver

#pragma mark - Lifecycle methods

- (instancetype)init {
    self = [super init];
    if (self) {
    }
    return self;
}

+ (instancetype)driver {
    static OAWebDriver *driver;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        driver = [[OAWebDriver alloc] init];
    });
    return driver;
}

#pragma mark - Public methods

/* Get */
- (NSURLSessionDataTask *)get:(NSString *)urlString
                   parameters:(NSDictionary *)parameters
                      headers:(NSDictionary *)headers
                      success:(OAWebDriverSuccessHandler)success
                      failure:(OAWebDriverFailureHandler)failure {
    
    NSURLSessionDataTask *task = [self.sessionManager GET:urlString
                                               parameters:parameters
                                                  headers:headers
                                                 progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        !success ?: success(responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        !failure ?: failure([OAError errorWithRawError:error]);
    }];
    
    return task;
}

/* Post */
- (NSURLSessionDataTask *)post:(NSString *)urlString
                    parameters:(NSDictionary *)parameters
                       headers:(NSDictionary *)headers
                       success:(OAWebDriverSuccessHandler)success
                       failure:(OAWebDriverFailureHandler)failure {
    
    NSURLSessionDataTask *task = [self.sessionManager POST:urlString
                                                parameters:parameters
                                                   headers:headers
                                                  progress:^(NSProgress * _Nonnull uploadProgress) {
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        !success ?: success(responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        !failure ?: failure([OAError errorWithRawError:error]);
    }];
    
    return task;
}

- (NSURLSessionDataTask *)post:(NSString *)urlString
                       rawData:(NSData *)rawData
                       headers:(NSDictionary *)headers
                       success:(OAWebDriverSuccessHandler)success
                       failure:(OAWebDriverFailureHandler)failure {
    
    NSURLRequest *request = [self requestWithUrlString:urlString rawData:rawData headers:headers ];
    
    NSURLSessionDataTask *task =
    [self.sessionManager dataTaskWithRequest:request uploadProgress:^(NSProgress * _Nonnull uploadProgress) {
    } downloadProgress:^(NSProgress * _Nonnull downloadProgress) {
    } completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
        if (error) {
            !failure ?: failure([OAError errorWithRawError:error]);
            return;
        }
        !success ?: success(responseObject);
    }];
    
    [task resume];
    
    return task;
    
}


/* Download */
- (NSURLSessionDataTask *)download:(NSString *)urlString
                       destination:(NSString *)destination
                          progress:(OAWebDriverProgressHandler)progress
                           success:(OAWebDriverSuccessHandler)success
                           failure:(OAWebDriverFailureHandler)failure {
    return nil;
}

/* Upload */
- (NSURLSessionDataTask *)upload:(NSString *)urlString
                      parameters:(NSDictionary *)parameters
                         headers:(NSDictionary *)headers
                        dataInfo:(NSDictionary *)dataInfo
                         success:(OAWebDriverSuccessHandler)success
                         failure:(OAWebDriverFailureHandler)failure {
    
    NSURLSessionDataTask *task = [self.sessionManager POST:urlString
                                                parameters:parameters
                                                   headers:headers
                                 constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
//        for (NSString *dataFieldName in dataInfo) {
//            [formData appendPartWithFileData:dataInfo[dataFieldName]
//                                        name:dataFieldName
//                                    fileName:@""
//                                    mimeType:@""];
//        };
        
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        !success ?: success(responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        !failure ?: failure([OAError errorWithRawError:error]);
    }];
    
    return task;
}

#pragma mark - Private methods

- (NSURLRequest *)requestWithUrlString:(NSString *)urlString
                               rawData:(NSData *)rawData
                               headers:(NSDictionary *)headers{
    
    NSMutableURLRequest *request = [[AFJSONRequestSerializer serializer] requestWithMethod:@"POST"
                                                                                 URLString:urlString
                                                                                parameters:nil
                                                                                     error:nil];
    request.timeoutInterval = OAWebDriver.config.timeoutInterval;
    for (NSString *headerFieldKey in headers) {
        [request setValue:headers[headerFieldKey] forHTTPHeaderField:headerFieldKey];
    }
    [request setHTTPBody:rawData];
    
    return request;
}

#pragma mark - Delegate methods



#pragma mark - Setter



#pragma mark - Getter

static OAWebDriverConfig *_config = nil;

+ (OAWebDriverConfig *)config {
    if (!_config) {
        _config = [[OAWebDriverConfig alloc] init];
    }
    return _config;
}

- (AFHTTPSessionManager *)sessionManager {
    if (!_sessionManager) {
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        
        //
        manager.requestSerializer = [AFHTTPRequestSerializer serializer];
        manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
        
        //
        if (OAWebDriver.config.responseType == OAWebResponseTypeJSON) {
            manager.responseSerializer = [AFJSONResponseSerializer serializer];
        }
        
        if (OAWebDriver.config.responseType == OAWebResponseTypeData) {
            manager.responseSerializer = [AFHTTPResponseSerializer serializer];
        }
        
        //
        NSArray *contentTypes = @[@"application/json",
                                  @"text/json",
                                  @"text/javascript",
                                  @"text/html",
                                  @"text/plain",
                                  @"text/xml",
                                  ];
        manager.responseSerializer.acceptableContentTypes = [NSSet setWithArray:contentTypes];
        
        _sessionManager = manager;
    }
    return _sessionManager;
}

#pragma mark - Memory management methods

- (void)dealloc {
}

@end
